//package com.dy.high.readt;
//
//import org.junit.Test;
//
//import java.io.*;
//import java.util.LinkedHashMap;
//import java.util.Map;
//
///**
// * @author huangdeyao
// * @date 2019/8/23 21:31
// */
//
//public class ReadTxtTest6 {
//    /**
//     * 头数据 这里使用LinkedHashMap 保证输入跟输出的顺序保持一致
//     */
//    private static Map<String, String> titleMap = new LinkedHashMap<>();
//    /**
//     * 定义一个与头信息一样的map 方便后面数据跟头数据的顺序保持一致
//     */
//    private static Map<String, String> contextMap = new LinkedHashMap<>();
//    /**
//     * 存一份缓存数据map
//     */
//    private Map<String, String> tempMap = new LinkedHashMap<>();
//    /**
//     * 基准时间
//     */
//    private long baseTime = 0;
//    /**
//     * 当前读取行号时间
//     */
//    private long nowTimes = 0;
//    /**
//     * 读取txt 数据
//     */
//    private BufferedReader br;
//
//    {
//        try {
//            br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("C://data_input//in_data.txt")), "UTF-8"));
//        } catch (UnsupportedEncodingException | FileNotFoundException e) {
//            e.printStackTrace();
//        }
//    }
//
//    /**
//     * 写入数据  Spring环境上可以考虑使用log日志方式
//     * <p>
//     * 写入数据地址
//     */
//    private BufferedWriter bw;
//
//    {
//        try {
//            bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("C://data_input//value_map.txt")), "UTF-8"));
//        } catch (UnsupportedEncodingException | FileNotFoundException e) {
//            e.printStackTrace();
//        }
//    }
//
//
//    /**
//     * 测试程序入口
//     */
//    @Test
//    public void dealData() throws IOException {
//        // 开时时间
//        long bTime1 = System.currentTimeMillis();
//        /**
//         * 主程序
//         */
//        readTxt();
//        //关闭总计时
//        long eTime1 = System.currentTimeMillis();
//        //输出
//        System.out.println("插入数据共耗时：" + (eTime1 - bTime1));
//    }
//
//    /**
//     * 读数据
//     */
//    private void readTxt() throws IOException {
//        try {
//            String lineTxt = null;
//            while ((lineTxt = br.readLine()) != null) {
//                // 数据切割
//                String[] strings = lineTxt.split(",");
//                // 第一行头数据截取后长度大于3，其他数据集合长度截取后长度为3，此处使用该条件判断当前行数是否为头
//                if (strings.length > 3) {
//                    // 装载头信息
//                    titleHandle(strings);
//                } else {
//                    // 处理数据
//                    handleContext(strings);
//                }
//            }
//
//            //代码写入执行为n - 1;所以会遗留一条数据，这里写入最后一条数据
//            /**
//             * 最后一条数据也有可能缺少时间点  这里继续传入递归处理
//             */
//            handleSwp(contextMap);
//            /**
//             * 最后一条数据 有可能是tag 这里需要更正一下 ,
//             */
//            tempMap.remove("tag");
//            contextMap.put("timestamp", String.valueOf(baseTime));
//            tempMap.put(String.valueOf(baseTime), handleString(contextMap));
//            System.out.println("tempMap = " + tempMap);
//            for (String name : tempMap.keySet()) {
//                writerHandle(tempMap.get(name));
//            }
//            /**
//             * 关闭
//             */
//            br.close();
//            bw.close();
//        } catch (Exception e) {
//            System.err.println("read errors :" + e);
//        } finally {
//            bw.close();
//        }
//    }
//
//    /**
//     * 组装完整数据 该方法执行完成后 contextMap中存储的是当前时间戳完整数据
//     *
//     * @param strings 切割数据
//     */
//    private void handleContext(String[] strings) throws IOException {
//        if (null != strings[0] && !"".equals(strings[0])) {
//            if (baseTime == 0) {
//                baseTime = Long.valueOf(strings[0]);
//            } else {
//                // 执行这里的时候 说明上一条数据已经组装完成
//                handleSwp(contextMap);
//            }
//            // 写入标准信号时间、
//            contextMap.put("timestamp", strings[0]);
//        }
//        // 将值写入map, map中的数据如果对应的编码有值，会修改，没有值继续保持之前的数据，
//        // 当前数据如果没有时间戳，此条数据会写入contextMap，不修改时间戳
//        handleMap(strings);
//    }
//
//    /**
//     * 使用递归处理数据逻辑
//     *
//     * @param contextMap
//     */
//    private void handleSwp(Map<String, String> contextMap) throws IOException {
//        nowTimes = Long.valueOf(contextMap.get("timestamp"));
//        // 如果当前时间等于基准时间 写入缓存tempMap 中
//        if (baseTime == nowTimes) {
//            tempMap.put(String.valueOf(baseTime), handleString(contextMap));
//            // 执行写入后 说明当前信号时间结束  开始下一个信号时间 此处 + 20ms
//            baseTime = baseTime + 20;
//            // 当上一个数据在下一个信号时间点上时，tag里有数据就会丢掉，所以这里也需要 查询一次
//            // 这条数据是 baseTime = baseTime + 20 时间戳上的数据
//            if (null != tempMap.get("tag") && !"".equals(tempMap.get("tag"))) {
//                String previousContext = tempMap.get("tag");
//                tempMap.remove("tag");
//                tempMap.put(String.valueOf(baseTime), previousContext);
//            }
//            // 写入数据
////            writeMapTxt(baseTime);
//        } else if (baseTime > nowTimes) {
//            // 基准时间大于当前信号时间，说明当前信号提前，更正时间，写入缓存tempMap 中； 这里不能 + 20ms 因为后面不知道是否还有数据在当前信号时间前
//            contextMap.put("timestamp", String.valueOf(baseTime));
//            tempMap.put("tag", handleString(contextMap));
//        } else {
//            // 这里说明时间信号延时 导致缺失； 缺失个数 n
//            // 这里先补充至少缺失的那一条数据 cp上一个信号量数据
//            String previousContext = null;
//            String nowTime = null;
//            // 先检查当前时间点 是否有小于信号点时间的数据  标记为tag
//            if (null != tempMap.get("tag") && !"".equals(tempMap.get("tag"))) {
//                previousContext = tempMap.get("tag");
//                nowTime = previousContext;
//                tempMap.remove("tag");
//            } else {
//                previousContext = tempMap.get(String.valueOf(baseTime - 20));
//                nowTime = previousContext.replaceFirst(String.valueOf(baseTime - 20), String.valueOf(baseTime));
//            }
//            // 更新的数据
//            tempMap.put(String.valueOf(baseTime), nowTime);
//            // 这里补充完后数据数据  说明至少缺失的那一条数据信号完成 所以这里需要步进一次
//            baseTime = baseTime + 20;
//            // 写入数据
////            writeMapTxt(baseTime);
//            handleSwp(contextMap);
//        }
//    }
//
//    /**
//     * 写入txt
//     */
//    private void writeMapTxt(long previousTime) throws IOException {
//        System.out.println("previousTime = " + previousTime);
//        if (tempMap.size() <= 2) {
//            /**
//             * 取出上一条数据
//             */
//            if (tempMap.size() == 2) {
//                previousTime = previousTime - 20;
//                String previousContext = tempMap.get(String.valueOf(previousTime));
//                if (null != previousContext && !"".equals(previousContext)) {
//                    // 这里可以找到值，说明时间戳已经走到了下一个 这里进行写入操作
//                    writerHandle(previousContext);
//                    tempMap.remove(String.valueOf(previousTime));
//                }
//            }
//        } else {
//            System.out.println(" =============程序执行异常，请检查数据 ========================= ");
//            System.out.println(" =============程序执行异常，请检查数据 ========================= ");
//            System.out.println("tempMap size = " + tempMap.size());
//            System.out.println(" =============程序执行异常，请检查数据 ========================= ");
//            System.out.println(" =============程序执行异常，请检查数据 ========================= ");
//            // 停止读取
//            br.close();
//            bw.close();
//        }
//    }
//
//    /**
//     * 写入txt
//     */
//    private void writerHandle(String string) {
//        try {
//            bw.write(string);
//            bw.newLine();
//        } catch (Exception e) {
//            System.err.println("write errors :" + e);
//        }
//    }
//
//    /**
//     * 装载头信息
//     *
//     * @param strings 读取的当前行数据
//     */
//    private void titleHandle(String[] strings) {
//        // 初始化数据存储map的时间戳
//        contextMap.put("timestamp", "0");
//        StringBuilder title = new StringBuilder("timestamp");
//        for (String str : strings) {
//            String[] headTxt = str.split(":");
//            // 头信息存入map 用于后面便利数据
//            titleMap.put(headTxt[1], headTxt[0]);
//            // 装载一个与头信息一样的map 方便后面数据跟头数据的顺序保持一致
//            contextMap.put(headTxt[1], "0");
//            // 组装头信息
//            title.append(";").append(headTxt[1]);
//        }
//        // 写入
//        writerHandle(String.valueOf(title));
//    }
//
//    /**
//     * 将数据中的值（contextMap）与头信息（titleMap）一一对应赋值
//     * 这里的数据 n  覆盖 n-1
//     *
//     * @param strings 读取的当前行数据
//     */
//    private void handleMap(String[] strings) {
//        // 查找当前数据 相对于头数据的属性
//        for (String name : titleMap.keySet()) {
//            if (titleMap.get(name).equals(strings[1])) {
//                contextMap.put(name, strings[2]);
//                // 如果当前时间节点数据组块里面有没有重复编码数据，此处找到数据后可以使用break;提高效率
//                break;
//            }
//        }
//    }
//
//    /**
//     * 将map 中的值 组装成string
//     *
//     * @param map
//     * @return
//     */
//    private String handleString(Map<String, String> map) {
//        // 将上一个timestamp 还原，否则当前时间为n+1行的时间，没有在赋值前做是因为如果数据为最后一行，将少一条数据
//        // 组装写入txt的 string
//        StringBuilder context = new StringBuilder();
//        for (String name : map.keySet()) {
//            // 这里为了删除最后一个；
//            if ("timestamp".equals(name)) {
//                context.append(map.get(name));
//            } else {
//                context.append(";").append(map.get(name));
//            }
//        }
//        return String.valueOf(context);
//    }
//}
